import LGXCOM from '../common/common.js'
import baseunitgrah from './baseunitgrah.js'
import { CoordTRFUtil } from '../common/tools/coordtool.js'

import GlobalConst from '../common/globalConst.js'
var global = GlobalConst.GlobalConst;

import UtilFuncs from '../common/tools/utilfuncs.js'
var funcs = UtilFuncs.UtilFuncs;
import { FillUtil } from '../graph/paintutil/fillutil.js'
import { LGXEnums } from '../common/sysenum.js'

import { Strokeutil } from '../graph/paintutil/strokeutil.js'

import pathinfo from '../common/struct/basestruct/pathinfo.js';
import pathcopysvc from '../service/copypaste/pathcopysvc.js';
import pathlink from './pathlink.js';

import fillCommStru from '../common/fillCommStru.js';

class PathGraph extends baseunitgrah.BaseUnitGraph {
    constructor(gid) {
        super(gid);
        this._position = new pathlink.PathCoordPos();
        this.m_graphType = LGXEnums.LGXGraphType.Path_type;
        this.m_PathLinkList = new Array();
        this._fillDef.fillStyle = LGXEnums.LGXFillStyle.Radial_CenterToTopMid;
    }

    getPathLinkList() { return this.m_PathLinkList; }

    display(map, mapInfo, forClip) {
        let trfFunc = this.convertWorldPt2Screen;
        this.paint(trfFunc, map, mapInfo, forClip)
    }

    disInSymbol(transformInfo, map, mapInfo, forClip) {
        let trfFunc = this.convertLocalPt2Screen;
        this.paint(trfFunc, map, mapInfo, forClip, transformInfo)
    }

    paint(trfFunc, map, mapInfo, forClip, transformInfo) {
        if (this.m_PathLinkList.length < 1) {
            return;
        }

        var scaling = mapInfo.getLenthDisScale();
        map.save();
        map.beginPath();
        let outPathLink = this.m_PathLinkList[0];
        this.displayPathUnitLink(trfFunc, outPathLink, map, mapInfo, transformInfo, false);
        for (let i = 1; i < this.m_PathLinkList.length; i++) {
            let innerPathLink = this.m_PathLinkList[i];
            this.displayPathUnitLink(trfFunc, innerPathLink, map, mapInfo, transformInfo, true);
        }

        let paintSymFlag = false;
        if (transformInfo) {
            paintSymFlag = true;
        }

        if (!forClip) {
            Strokeutil.active(this._lineDef, this, map, mapInfo);
            FillUtil.active(this._fillDef, map, this, mapInfo, paintSymFlag, transformInfo);
        }
        map.restore();

        if (!transformInfo) {
            super.displayGraphScope(map, mapInfo);
            this.displayFeaturePoint(map, mapInfo);
        }
    }

    displayPathUnitLink(trfFunc, pathLink, map, mapInfo, transformInfo, innerEdge) {
        let stUnit = pathLink.getPathStartUnit();
        this.displayPathUnit(trfFunc, true, stUnit, map, mapInfo, transformInfo, innerEdge);
    }

    displayPathUnit(trfFunc, startNodeFlag, pathUnit, map, mapInfo, transformInfo, innerEdge) {
        if (pathUnit.type == fillCommStru.PathUnitType.line
            || pathUnit.type == fillCommStru.PathUnitType.polygon) {
            let polyposition = pathUnit.coordDecs;
            this.displayPolylineUnit(trfFunc, startNodeFlag, polyposition, map, mapInfo, transformInfo, pathUnit.independentRegion)
        }
        else if (pathUnit.type == fillCommStru.PathUnitType.arc) {
            let arcPosition = pathUnit.coordDecs;
            this.displayArcUnit(trfFunc, startNodeFlag, arcPosition, map, mapInfo, transformInfo, innerEdge)
        }
        else if (pathUnit.type == fillCommStru.PathUnitType.circle) {
            let arcPosition = pathUnit.coordDecs;
            this.displayCircleUnit(trfFunc, startNodeFlag, arcPosition, map, mapInfo, transformInfo, innerEdge)
        }
        else if (pathUnit.type == fillCommStru.PathUnitType.rect) {
            let rectPosition = pathUnit.coordDecs;
            this.displayRectUnit(trfFunc, startNodeFlag, rectPosition, map, mapInfo, transformInfo, pathUnit.independentRegion)
        }
        else if (pathUnit.type == fillCommStru.PathUnitType.spline) {
            let rectPosition = pathUnit.coordDecs;
            this.displaySplineUnit(trfFunc, startNodeFlag, rectPosition, map, mapInfo, transformInfo, pathUnit.independentRegion)
        }
        else if (pathUnit.type == fillCommStru.PathUnitType.ellipseArc) {
            this.displayEllipseArcUnit(trfFunc, startNodeFlag, pathUnit.coordDecs, map, mapInfo, transformInfo, pathUnit.independentRegion)
        }
        else if (pathUnit.type == fillCommStru.PathUnitType.bezier) {
            let rectPosition = pathUnit.coordDecs;
            this.displayBezierUnit(trfFunc, startNodeFlag, rectPosition, map, mapInfo, transformInfo, pathUnit.independentRegion)
        }

        let nextUnit = pathUnit.nextUnit;
        if (nextUnit) {
            this.displayPathUnit(trfFunc, false, nextUnit, map, mapInfo, transformInfo, innerEdge);
        }
    }

    displayPolylineUnit(trfFunc, startNodeFlag, position, map, mapInfo, transformInfo, independentRegion) {
        let linePtList = position.posList;
        if (startNodeFlag) {
            let p0 = linePtList[0];
            var spt = trfFunc(p0, mapInfo, transformInfo);
            map.moveTo(spt.x, spt.y);
            let stx = spt.x;
            let sty = spt.y;
            for (let i = 1; i < linePtList.length; i++) {
                let pt = linePtList[i];
                var spt = trfFunc(pt, mapInfo, transformInfo);
                map.lineTo(spt.x, spt.y);
            }
            if (independentRegion) {
                map.lineTo(stx, sty);
            }
        }
        else {
            for (let i = 1; i < linePtList.length; i++) {
                let pt = linePtList[i];
                var spt = trfFunc(pt, mapInfo, transformInfo);
                map.lineTo(spt.x, spt.y);
            }
        }

    }

    displayArcUnit(trfFunc, startNodeFlag, postion, map, mapInfo, transformInfo) {
        if (startNodeFlag) {
            let arcPtInfo = funcs.getArcControlPoint(postion);
            let p0 = arcPtInfo.stPoint;
            var spt = trfFunc(p0, mapInfo, transformInfo);
            map.moveTo(spt.x, spt.y);
        }

        var scaling = mapInfo.getLenthDisScale();
        let disYScale = 1;
        let disRadius = scaling * postion.radius;
        let rotv = 0;
        if (transformInfo){
            disYScale = transformInfo.sy/transformInfo.sx;
            disRadius = scaling * postion.radius*transformInfo.sx;
            rotv = transformInfo.rotRad;
        }
        
        
        var cntpt = { x: postion.x, y: postion.y };
        var screenCnt = trfFunc(cntpt, mapInfo, transformInfo);

        let stAngleRad = Math.PI * 2 - funcs.degree2Radian(postion.stAngle);
        let endAngleRad = Math.PI * 2 - funcs.degree2Radian(postion.endAngle);
        let flag = postion.antiClockWise;

        
        map.save();
        map.translate(screenCnt.x, screenCnt.y);
        map.rotate(-rotv);
        map.scale(1,disYScale);
        // map.beginPath();
        map.arc(0,0, disRadius, stAngleRad, endAngleRad, flag);
        map.restore();
    }

    displayCircleUnit(trfFunc, startNodeFlag, postion, map, mapInfo, transformInfo, innerFlag) {
        var scaling = mapInfo.getLenthDisScale();
        var disRadius = scaling * postion.radius;
        var cntpt = { x: postion.x, y: postion.y };
        var screenCnt = trfFunc(cntpt, mapInfo, transformInfo);

        if (startNodeFlag) {
            map.moveTo(screenCnt.x + disRadius, screenCnt.y);
        }

        map.ellipse(screenCnt.x, screenCnt.y, disRadius, disRadius, 0, 0, Math.PI * 2, !innerFlag);
    }

    displayRectUnit(trfFunc, startNodeFlag, position, map, mapInfo, transformInfo) {
        let linePtList = position.posList;
        let posCount = linePtList.length;
        let p0 = linePtList[0];
        let spt0 = trfFunc(p0, mapInfo);
        map.moveTo(spt0.x, spt0.y);
        for (let i = 1; i < posCount; i++) {
            let pt = linePtList[i];
            var spt = trfFunc(pt, mapInfo, transformInfo);
            map.lineTo(spt.x, spt.y);
        }
        map.lineTo(spt0.x, spt0.y);
    }


    displaySplineUnit(trfFunc, startNodeFlag, position, map, mapInfo, transformInfo) {
        let disPtList = [];
        let posList = position.posList;
        let i = 0;
        for (i = 0; i < posList.length; i++) {
            let pt = posList[i];
            var spt = trfFunc(pt, mapInfo, transformInfo);
            disPtList.push(spt);
        }

        let p0 = disPtList[0];
        if (startNodeFlag) {
            map.moveTo(p0.x, p0.y);
        }

        for (i = 1; i < disPtList.length - 2; i++) {
            var xc = (disPtList[i].x + disPtList[i + 1].x) / 2;
            var yc = (disPtList[i].y + disPtList[i + 1].y) / 2;
            map.quadraticCurveTo(disPtList[i].x, disPtList[i].y, xc, yc);
        }

        // 通过最后两个点绘制最后一段曲线
        map.quadraticCurveTo(disPtList[i].x, disPtList[i].y, disPtList[i + 1].x, disPtList[i + 1].y);
    }

    displayEllipseArcUnit(trfFunc, startNodeFlag, postion, map, mapInfo, transformInfo) {
        if (startNodeFlag) {
            let arcPtInfo = funcs.getEllipseArcControlPoint(postion);
            let p0 = arcPtInfo.stPoint;
            var spt = trfFunc(p0, mapInfo, transformInfo);
            map.moveTo(spt.x, spt.y);
        }

        var scaling = mapInfo.getLenthDisScale();
        var disxRadius = scaling * postion.xRadius;
        var disyRadius = scaling * postion.yRadius;
        var cntpt = { x: postion.x, y: postion.y };
        var screenCnt = trfFunc(cntpt, mapInfo, transformInfo);

        let stAngleRad = Math.PI * 2 - funcs.degree2Radian(postion.stAngle);
        let endAngleRad = Math.PI * 2 - funcs.degree2Radian(postion.endAngle);
        map.ellipse(screenCnt.x, screenCnt.y, disxRadius, disyRadius, 0, stAngleRad, endAngleRad, postion.antiClockWise);
    }

    calScope(mapscale) {
        if (this.m_PathLinkList.length == 0) {
            return;
        }
        let outPathLink = this.m_PathLinkList[0];
        let stUnit = outPathLink.getPathStartUnit();
        if (stUnit) {
            let rect = outPathLink.calScope(mapscale);
            this._zone.clone(rect);
            // console.log("path zone:");
            // console.log(rect);
        }
    }

    getLocalZone() {
        let mtx = this.getLocalMatrix();
        let inverseMtx = mtx.Inverse();
        let rect = new LGXCOM.LGXRect(0, 0, 0, 0);
        let posList = this.getControlPointList();
        let length = posList.length;
        for (var i = 0; i < length; i++) {
            let pt = posList[i];
            let localPt = inverseMtx.MultT({ x: pt.x, y: pt.y, z: 0 });//求相对于控制图形局部坐标系的局部坐标  
            let x = localPt.x;
            let y = localPt.y;

            if (i == 0) {
                rect.left = x;
                rect.right = x;
                rect.top = y;
                rect.bottom = y;
            }
            rect.left = Math.min(rect.left, x);
            rect.right = Math.max(rect.right, x);
            rect.bottom = Math.min(rect.bottom, y);
            rect.top = Math.max(rect.top, y);
        }
        return rect;
    }

    getControlPointList() {
        let posList = [];
        let rect = this.getZone();
        posList.push(rect.ltPt());
        posList.push(rect.lbPt());
        posList.push(rect.rtPt());
        posList.push(rect.rbPt());
        return posList;
    }

    distance(tPos, scaling, mapscale) {
        if (!super.preCheckInScope(tPos, scaling)) {
            return -1;
        }

        return 0;
    }


    calculateSubKind(tPoint, scaling, mapscale) {
        let dis = this.distance(tPoint, scaling, mapscale);
        if (Math.abs(dis) < global.ZERO_8E) {
            return 1;
        }
        else {
            return 0;
        }
    }

    movePosOffset(tOffset, modCmdInfo) {
        console.log("path graph tanslate*****************");
        if (this._selKind < 1) {
            return;
        }
        if (this._selKind == 1) {
            this.translateAllUnit(tOffset, modCmdInfo);
        }
    }

    assignInfo(info) {
        super.assignInfo(info);
        pathcopysvc.PathGraphCopySvc.copyPathProp(info, this, 0, 0);
    }

    toInfo() {
        if (this.m_PathLinkList.length == 0) {
            this.setUseful(0);
        }
        var info = new pathinfo.PathInfo();
        this.toInfo4InheritClass(info);
        info.pathDesc = this._position.toString();
        return info;
    }

    modifyCoord(propName, propVal, mapscale) {

    }

    getCoordInfo() {

    }

    getCoordPropDef() {

    }

    addPathLink(pathlink) {
        if (pathlink) {
            this.m_PathLinkList.push(pathlink);
            if (this._position.pathLinkList.indexOf(pathlink) == -1) {
                this._position.pathLinkList.push(pathlink);
            }
        }
        else {
            console.log("invalid pathlink *****************");
        }
    }

    displayFeaturePoint(map, mapInfo) {
        if (!this._selected) {
            return;
        }
        let outPathLink = this.m_PathLinkList[0];
        let stUnit = outPathLink.getPathStartUnit();
        this.displayUnitFeaturePoint(stUnit, map, mapInfo);
        return;
    }

    displayUnitFeaturePoint(pathUnit, map, mapInfo) {
        let pos = pathUnit.coordDecs;
        if (pathUnit.type == 'line') {
            this.displayPolylineUnitFeature(pos, map, mapInfo);
        }
        else if (pathUnit.type == 'arc') {
            this.displayArcUnitFeature(pos, map, mapInfo);
        }
        let nextUnit = pathUnit.nextUnit;
        if (nextUnit) {
            this.displayUnitFeaturePoint(nextUnit, map, mapInfo);
        }
    }

    displayPolylineUnitFeature(position, map, mapInfo) {
        let linePtList = position.posList;
        for (let i = 0; i < linePtList.length; i++) {
            let pt = linePtList[i];
            var spt = CoordTRFUtil.world2Screen(pt, mapInfo);
            super.drawFocusPoint(map, spt.x, spt.y, "#0000ff");
        }
    }

    displayArcUnitFeature(postion, map, mapInfo) {
        let stAngleRad = funcs.degree2Radian(postion.stAngle);
        let endAngleRad = funcs.degree2Radian(postion.endAngle);

        let ptlst = [];
        //起点
        let x = postion.x + postion.radius * Math.cos(stAngleRad);
        let y = postion.y + postion.radius * Math.sin(stAngleRad);
        let ctrlPt = { x, y };
        ptlst.push(ctrlPt);

        //中间点
        let midDotAngle = (stAngleRad + endAngleRad) / 2;
        x = postion.x + postion.radius * Math.cos(midDotAngle);
        y = postion.y + postion.radius * Math.sin(midDotAngle);
        ctrlPt = { x, y };
        ptlst.push(ctrlPt);

        //终止点
        x = postion.x + postion.radius * Math.cos(endAngleRad);
        y = postion.y + postion.radius * Math.sin(endAngleRad);
        ctrlPt = { x, y };
        ptlst.push(ctrlPt);

        for (let i = 0; i < ptlst.length; i++) {
            let pt = ptlst[i];
            var spt = CoordTRFUtil.world2Screen(pt, mapInfo);
            super.drawFocusPoint(map, spt.x, spt.y, "#0000ff");
        }

    }

    rotateCoord(rotCnt, radAngle) {
        let pathCoordPos = this.getPosCopy();
        pathCoordPos.rotate(rotCnt, radAngle);
        this.setPos(pathCoordPos);
        super.rotateGradientFill(rotCnt, radAngle);
        this.rotateConnTopo(rotCnt, radAngle);
    }

    translate(offset, mapscale) {
        this.translateAllUnit(offset);
        this.translateGradientFill(offset);
    }

    translateAllUnit(tOffset) {
        for (let i = 0; i < this.m_PathLinkList.length; i++) {
            let outPathLink = this.m_PathLinkList[i];
            let stUnit = outPathLink.getPathStartUnit();
            this.transUnit(stUnit, tOffset);
        }
        return;
    }

    transUnit(pathUnit, tOffset) {
        let pos = pathUnit.coordDecs;
        if (pos) {
            pos.offset(tOffset.x, tOffset.y);
        }
        let nextUnit = pathUnit.nextUnit;
        if (nextUnit) {
            this.transUnit(nextUnit, tOffset);
        }
    }

    scale(basePt, sx, sy) {
        for (let i = 0; i < this.m_PathLinkList.length; i++) {
            let outPathLink = this.m_PathLinkList[i];
            let stUnit = outPathLink.getPathStartUnit();
            this.scaleUnit(stUnit, basePt, sx, sy);
        }
        return;
    }

    scaleUnit(pathUnit, basePt, sx, sy) {
        let pos = pathUnit.coordDecs;
        if (pos) {
            pos.scale(basePt, sx, sy);
        }
        let nextUnit = pathUnit.nextUnit;
        if (nextUnit) {
            this.scaleUnit(nextUnit, basePt, sx, sy);
        }
    }

    getRelateAllPathUnit() {
        let tAllPathUnitArr = [];
        for (let i = 0; i < this.m_PathLinkList.length; i++) {
            let pathLink = this.m_PathLinkList[i];
            pathLink.getRelatePathUnit(null, tAllPathUnitArr);
        }
        return tAllPathUnitArr;
    }

    getPosCopy() {
        let copyPathCoordPos = new pathlink.PathCoordPos();
        let dstPathLinkList = this.getPathLinkList();
        for (let i = 0; i < dstPathLinkList.length; i++) {
            let link = dstPathLinkList[i];
            let copyPathLink = new pathlink.PathUnitLink();
            copyPathLink.clone(link);
            copyPathCoordPos.pathLinkList.push(copyPathLink);
        }
        return copyPathCoordPos;
    }

    setPos(srcPathCoordPos) {
        this._position.pathLinkList = [];
        this.m_PathLinkList = [];
        for (let i = 0; i < srcPathCoordPos.pathLinkList.length; i++) {
            let link = srcPathCoordPos.pathLinkList[i];
            let copyPathLink = new pathlink.PathUnitLink();
            copyPathLink.clone(link);
            this.m_PathLinkList.push(copyPathLink);
            this._position.pathLinkList.push(copyPathLink);
        }
        this.calScope(1);
    }

    getMainFeaturePTLst(tFeaturePTLst, transformInfo) {
        for (let i = 0; i < this.m_PathLinkList.length; i++) {
            let pathLink = this.m_PathLinkList[i];
            pathLink.getMainFeaturePTLst(tFeaturePTLst, transformInfo);
        }
    }



    clipFillZone_ex(map, mapInfo, transformInfo) {
        if (this.m_PathLinkList.length < 1) {
            return 0;
        }
        map.clip();
        let outPathLink = this.m_PathLinkList[0];
        map.beginPath();
        this.displayPathUnitLink(outPathLink, map, mapInfo, false);
        for (let i = 1; i < this.m_PathLinkList.length; i++) {
            let innerPathLink = this.m_PathLinkList[i];
            this.displayPathUnitLink(innerPathLink, map, mapInfo, true);
        }
        return 1;
    }

    //复制粘贴时，从复制源对象复制属性到本图形对应属性----虚函数，由实体继承类实现
    copySubPropFromBuf(bufInfo, tx, ty) {
        pathcopysvc.PathGraphCopySvc.copyPathProp(bufInfo, this, tx, ty)
        this.copyCommnonPropFromBuf(bufInfo, tx, ty);
    }

    displayBezierUnit(trfFunc, startNodeFlag, position, map, mapInfo, transformInfo) {
        if (position.posList.length != 4){
            return ;
        }
        let disPtList = [];
        let posList = position.posList;
        for (let i = 0; i < posList.length; i++) {
            let pt = posList[i];
            let spt = trfFunc(pt, mapInfo, transformInfo);
            disPtList.push(spt);
        }

        let p0 = disPtList[0];
        let p1 = disPtList[1];
        let p2 = disPtList[2];
        let p3 = disPtList[3];
        if (startNodeFlag) {
            map.moveTo(p0.x, p0.y);
        }
        map.bezierCurveTo(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y);
    }
}

export default { PathGraph }
